#pragma once
#include "DJoint.h"

namespace Skill
{
	namespace Ode
	{
		ref class DWorld;
		ref class DVector3;

		namespace Joints
		{
			public enum class DAngularMotorMode
			{			
				User = dAMotorUser,
				Euler = dAMotorEuler
			};

			ref class DJointGroup;
			public ref class DAngularMotor : DJoint
			{			
			public:

				///<summary>
				/// Create a new joint of the A-motor type.
				///</summary>
				///<param name = "world"> Wrold </param>
				///<param name = "group">
				/// set to null to allocate the joint normally.
				/// If it is valid the joint is allocated in the given joint group.
				///</param>
				DAngularMotor(DWorld^ world , DJointGroup^ group);



				///<summary>
				/// Gets or set the number of angular axes that will be controlled by the DAngularMotor			
				/// num can range from 0 (which effectively deactivates the
				/// joint) to 3.
				/// This is automatically set to 3 in dAMotorEuler mode.
				///</summary>			
				VALUE_PROP_DECLARATION_GETSET(int,NumAxes);

				///<summary>
				/// set axis
				///</summary>
				void SetAxis( int anum, int rel, dReal x, dReal y, dReal z);

				///<summary>
				/// set axis
				///</summary>
				///<param name = "anum"> selects the axis to change (0,1 or 2). </param>
				///<param name = "rel"> Each axis can have one of three ``relative orientation'' modes.
				///  0: The axis is anchored to the global frame.
				///  1: The axis is anchored to the first body.
				///  2: The axis is anchored to the second body.
				///</param>
				void SetAxis( int anum, int rel, DVector3^ asis);

				///<summary>
				/// Tell the AMotor what the current angle is along axis anum.
				///
				/// This function should only be called in dAMotorUser mode, because in this
				/// mode the AMotor has no other way of knowing the joint angles.
				/// The angle information is needed if stops have been set along the axis,
				/// but it is not needed for axis motors.
				///</summary>
				void SetAngle(int anum, dReal angle);

				///<summary>
				/// set joint parameter
				///</summary>
				void SetParam(DJointParameters parameter, dReal value);

				///<summary>
				/// Gets or set the angular motor mode.
				/// must be one of the following constants:
				/// \li dAMotorUser The AMotor axes and joint angle settings are entirely
				/// controlled by the user.  This is the default mode.
				/// \li dAMotorEuler Euler angles are automatically computed.
				/// The axis a1 is also automatically computed.
				/// The AMotor axes must be set correctly when in this mode,
				/// as described below.
				/// When this mode is initially set the current relative orientations
				/// of the bodies will correspond to all euler angles at zero.			
				///</summary>				
				VALUE_PROP_DECLARATION_GETSET(DAngularMotorMode,Mode);


				///<summary>								
				/// Applies torque0 about the AMotor's axis 0, torque1 about the
				/// AMotor's axis 1, and torque2 about the AMotor's axis 2.
				///</summary>
				///<remarks>			
				/// If the motor has fewer than three axes, the higher torques are ignored.
				/// This function is just a wrapper for dBodyAddTorque().
				///</remarks>
				void AddTorques(dReal torque1, dReal torque2, dReal torque3);

				///<summary>
				/// Get the AngularMotor axes.
				///</summary>
				///<param name = "anum"> selects the axis to change (0,1 or 2). </param>			
				void GetAxis(int anum, int rel , DVector3^ result);

				///<summary>
				/// Get axis
				///</summary>
				///<remarks>
				/// The axis vector is always specified in global coordinates regardless
				/// of the setting of rel.
				/// There are two GetAMotorAxis functions, one to return the axis and one to
				/// return the relative mode.
				///
				/// For dAMotorEuler mode:
				/// 	Only axes 0 and 2 need to be set. Axis 1 will be determined
				///automatically at each time step.
				/// 	Axes 0 and 2 must be perpendicular to each other.
				/// 	Axis 0 must be anchored to the first body, axis 2 must be anchored
				///to the second body.			
				///</remarks>
				int GetAxisRel(int anum);

				///<summary>
				/// Get the current angle for axis.
				///</summary>
				///<remarks>
				/// In dAMotorUser mode this is simply the value that was set with SetAngle().
				/// In dAMotorEuler mode this is the corresponding euler angle.
				///</remarks>
				dReal GetAngle(int anum);

				///<summary>
				/// Get the current angle rate for axis anum.
				///</summary>
				///<remarks>
				/// In dAMotorUser mode this is always zero, as not enough information is
				/// available.
				/// In dAMotorEuler mode this is the corresponding euler angle rate.
				///</remarks>			
				dReal GetAngleRate(int anum);			

				///<summary>
				/// Get joint parameter
				///</summary>
				dReal GetParam(DJointParameters parameter);				
			};
		}
	}
}